package com.zzjson.netty.rpc.registry;

import com.zzjson.netty.rpc.protocol.InvokerProtocol;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <p>****************************************************************************</p>
 * <p><b>Copyright © 2010-2020 shuncom team All Rights Reserved<b></p>
 * <ul style="margin:15px;">
 * <li>Description : com.zzjson.netty.rpc.registry</li>
 * <li>Version     : 1.0.0</li>
 * <li>Creation    : 2020年03月03日</li>
 * <li>@author     : zzy0_0</li>
 * </ul>
 * <p>****************************************************************************</p>
 */
public class RegistryHandler extends ChannelInboundHandlerAdapter {
	private List<String> classNames = new ArrayList<>();

	private Map<String, Object> registryMap = new ConcurrentHashMap<>();

	public RegistryHandler() {
		//1.根据一个包名，把所有符合条件的Class全部扫描出来，放到一个容器中
		scannerClass("com.zzjson.netty.rpc.provider");

		//2.扫描出来之后，给每一个对应的class起一个名字，作为服务名称，保存到一个容器中
		doRegistry();


		//3.当有客户端连接上的时候，就能够获取协议内容 InvokerProtocol的对象

		//4.要去注册好的容器中找服务

		//5.在provider中找结果，并且返回给客户端
	}

	private void doRegistry() {
		if (classNames.isEmpty()) {
			return;
		}
		for (String className : classNames) {
			try {
				Class<?> clazz = Class.forName(className);
				//接口名称作为服务名
				Class<?> anInterface = clazz.getInterfaces()[0];

				String serviceName = anInterface.getName();
				//本来这里存的应该是网络路径，从配置文件读取
				//在调用的时候再去解析，直接通过反射调用
				registryMap.put(serviceName, clazz.newInstance());
			} catch (Exception e) {
				e.printStackTrace();
			}

		}
	}

	/**
	 * 正常是读配置文件
	 */
	private void scannerClass(String packageName) {
		URL url = this.getClass().getClassLoader().getResource(packageName.replaceAll("\\.", "/"));
		File classpath = new File(url.getFile());
		for (File file : classpath.listFiles()) {
			if (file.isDirectory()) {
				scannerClass(packageName + "." + file.getName());
			} else {
				classNames.add(packageName + "." + file.getName().replace(".class", ""));
			}
		}
	}


	/**
	 * 有客户端连上的时候，回回调当前方法
	 */
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		Object result = new Object();
		InvokerProtocol request = (InvokerProtocol) msg;
		if (registryMap.containsKey(request.getClassName())) {
			Object service = registryMap.get(request.getClassName());
			Method method = service.getClass().getMethod(request.getMethodName(), request.getParams());
			result = method.invoke(service, request.getValues());
		}
		ctx.write(result);
		ctx.flush();
		ctx.close();

	}

	/**
	 * 连接发生异常的时候回调
	 *
	 * @param ctx
	 * @param cause
	 * @throws Exception
	 */
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		super.exceptionCaught(ctx, cause);
	}
}
